home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / g__~1 / gplibs15.zoo / xgetopt.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-01  |  8.5 KB  |  258 lines

  1. /*
  2. Getopt for GNU. 
  3. Copyright (C) 1987, 1989 Free Software Foundation, Inc.
  4.  
  5. (Modified by Douglas C. Schmidt for use with GNU G++.)
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. #ifdef __GNUG__
  20. #pragma implementation
  21. #endif
  22. /* AIX requires the alloca decl to be the first thing in the file. */
  23. #ifdef __GNUC__
  24. #define alloca __builtin_alloca
  25. #elif defined(sparc)
  26. #include <alloca.h>
  27. #elif defined(_AIX)
  28. #pragma alloca
  29. #else
  30. char *alloca ();
  31. #endif
  32. #include <xgetopt.h>
  33.  
  34. char* GetOpt::nextchar = 0;
  35. int GetOpt::first_nonopt = 0;
  36. int GetOpt::last_nonopt = 0;
  37. #if (__GNUG__ == 1) 
  38. OrderingEnum GetOpt::ordering = GetOpt::REQUIRE_ORDER;
  39. #else
  40. GetOpt::OrderingEnum GetOpt::ordering = GetOpt::REQUIRE_ORDER;
  41. #endif /* (__GNUG__ == 1)  */
  42.  
  43. GetOpt::GetOpt (int argc, char **argv, const char *optstring)
  44.  :opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
  45. {
  46.   /* Initialize the internal data when the first call is made.
  47.      Start processing options with ARGV-element 1 (since ARGV-element 0
  48.      is the program name); the sequence of previously skipped
  49.      non-option ARGV-elements is empty.  */
  50.  
  51.   first_nonopt = last_nonopt = optind = 1;
  52.   optarg = nextchar = 0;
  53.  
  54.   /* Determine how to handle the ordering of options and nonoptions.  */
  55.  
  56.   if (optstring[0] == '-')
  57.     ordering = RETURN_IN_ORDER;
  58.   else if (getenv ("_POSIX_OPTION_ORDER") != 0)
  59.     ordering = REQUIRE_ORDER;
  60.   else
  61.     ordering = PERMUTE;
  62. }
  63.  
  64. void
  65. GetOpt::exchange (char **argv)
  66. {
  67.   size_t nonopts_size
  68.     = (last_nonopt - first_nonopt) * sizeof (char *);
  69.   char **temp = (char **) alloca (nonopts_size);
  70.  
  71.   /* Interchange the two blocks of data in argv.  */
  72.  
  73.   bcopy (&argv[first_nonopt], temp, nonopts_size);
  74.   bcopy (&argv[last_nonopt], &argv[first_nonopt],
  75.          (optind - last_nonopt) * sizeof (char *));
  76.   bcopy (temp, &argv[first_nonopt + optind - last_nonopt],
  77.          nonopts_size);
  78.  
  79.   /* Update records for the slots the non-options now occupy.  */
  80.  
  81.   first_nonopt += (optind - last_nonopt);
  82.   last_nonopt = optind;
  83. }
  84.  
  85. /* Scan elements of ARGV (whose length is ARGC) for option characters
  86.    given in OPTSTRING.
  87.  
  88.    If an element of ARGV starts with '-', and is not exactly "-" or "--",
  89.    then it is an option element.  The characters of this element
  90.    (aside from the initial '-') are option characters.  If `getopt'
  91.    is called repeatedly, it returns successively each of theoption characters
  92.    from each of the option elements.
  93.  
  94.    If `getopt' finds another option character, it returns that character,
  95.    updating `optind' and `nextchar' so that the next call to `getopt' can
  96.    resume the scan with the following option character or ARGV-element.
  97.  
  98.    If there are no more option characters, `getopt' returns `EOF'.
  99.    Then `optind' is the index in ARGV of the first ARGV-element
  100.    that is not an option.  (The ARGV-elements have been permuted
  101.    so that those that are not options now come last.)
  102.  
  103.    OPTSTRING is a string containing the legitimate option characters.
  104.    A colon in OPTSTRING means that the previous character is an option
  105.    that wants an argument.  The argument is taken from the rest of the
  106.    current ARGV-element, or from the following ARGV-element,
  107.    and returned in `optarg'.
  108.  
  109.    If an option character is seen that is not listed in OPTSTRING,
  110.    return '?' after printing an error message.  If you set `opterr' to
  111.    zero, the error message is suppressed but we still return '?'.
  112.  
  113.    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
  114.    so the following text in the same ARGV-element, or the text of the following
  115.    ARGV-element, is returned in `optarg.  Two colons mean an option that
  116.    wants an optional arg; if there is text in the current ARGV-element,
  117.    it is returned in `optarg'.
  118.  
  119.    If OPTSTRING starts with `-', it requests a different method of handling the
  120.    non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.  */
  121.  
  122. int
  123. GetOpt::operator () (void)
  124. {
  125.   if (nextchar == 0 || *nextchar == 0)
  126.     {
  127.       if (ordering == PERMUTE)
  128.         {
  129.           /* If we have just processed some options following some non-options,
  130.              exchange them so that the options come first.  */
  131.  
  132.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  133.             exchange (nargv);
  134.           else if (last_nonopt != optind)
  135.             first_nonopt = optind;
  136.  
  137.           /* Now skip any additional non-options
  138.              and extend the range of non-options previously skipped.  */
  139.  
  140.           while (optind < nargc
  141.                  && (nargv[optind][0] != '-'
  142.                      || nargv[optind][1] == 0))
  143.             optind++;
  144.           last_nonopt = optind;
  145.         }
  146.  
  147.       /* Special ARGV-element `--' means premature end of options.
  148.          Skip it like a null option,
  149.          then exchange with previous non-options as if it were an option,
  150.          then skip everything else like a non-option.  */
  151.  
  152.       if (optind != nargc && !strcmp (nargv[optind], "--"))
  153.         {
  154.           optind++;
  155.  
  156.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  157.             exchange (nargv);
  158.           else if (first_nonopt == last_nonopt)
  159.             first_nonopt = optind;
  160.           last_nonopt = nargc;
  161.  
  162.           optind = nargc;
  163.         }
  164.  
  165.       /* If we have done all the ARGV-elements, stop the scan
  166.          and back over any non-options that we skipped and permuted.  */
  167.  
  168.       if (optind == nargc)
  169.         {
  170.           /* Set the next-arg-index to point at the non-options
  171.              that we previously skipped, so the caller will digest them.  */
  172.           if (first_nonopt != last_nonopt)
  173.             optind = first_nonopt;
  174.           return EOF;
  175.         }
  176.      
  177.       /* If we have come to a non-option and did not permute it,
  178.          either stop the scan or describe it to the caller and pass it by.  */
  179.  
  180.       if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
  181.         {
  182.           if (ordering == REQUIRE_ORDER)
  183.             return EOF;
  184.           optarg = nargv[optind++];
  185.           return 0;
  186.         }
  187.  
  188.       /* We have found another option-ARGV-element.
  189.          Start decoding its characters.  */
  190.  
  191.       nextchar = nargv[optind] + 1;
  192.     }
  193.  
  194.   /* Look at and handle the next option-character.  */
  195.  
  196.   {
  197.     char c = *nextchar++;
  198.     char *temp = (char *) index (noptstring, c);
  199.  
  200.     /* Increment `optind' when we start to process its last character.  */
  201.     if (*nextchar == 0)
  202.       optind++;
  203.  
  204.     if (temp == 0 || c == ':')
  205.       {
  206.         if (opterr != 0)
  207.           {
  208.             if (c < 040 || c >= 0177)
  209.               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
  210.                        nargv[0], c);
  211.             else
  212.               fprintf (stderr, "%s: unrecognized option `-%c'\n",
  213.                        nargv[0], c);
  214.           }
  215.         return '?';
  216.       }
  217.     if (temp[1] == ':')
  218.       {
  219.         if (temp[2] == ':')
  220.           {
  221.             /* This is an option that accepts an argument optionally.  */
  222.             if (*nextchar != 0)
  223.               {
  224.                 optarg = nextchar;
  225.                 optind++;
  226.               }
  227.             else
  228.               optarg = 0;
  229.             nextchar = 0;
  230.           }
  231.         else
  232.           {
  233.             /* This is an option that requires an argument.  */
  234.             if (*nextchar != 0)
  235.               {
  236.                 optarg = nextchar;
  237.                 /* If we end this ARGV-element by taking the rest as an arg,
  238.                    we must advance to the next element now.  */
  239.                 optind++;
  240.               }
  241.             else if (optind == nargc)
  242.               {
  243.                 if (opterr != 0)
  244.                   fprintf (stderr, "%s: no argument for `-%c' option\n",
  245.                            nargv[0], c);
  246.                 c = '?';
  247.               }
  248.             else
  249.               /* We already incremented `optind' once;
  250.                  increment it again when taking next ARGV-elt as argument.  */
  251.               optarg = nargv[optind++];
  252.             nextchar = 0;
  253.           }
  254.       }
  255.     return c;
  256.   }
  257. }
  258.